package demo03;

import lombok.Data;
import lombok.SneakyThrows;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.sql.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

@Data
class User {
    private Long id;
    private String name;
    private String password;
    private String address;
}

public class SelectTest {
    @SneakyThrows
    public static void main(String[] args) {
        Connection connection = getConnection("jdbc:mysql://localhost:3306/test2", "root", "mysql");
        String sql = "select * from user";
        List<User> users = selectAll(sql, User.class, connection);
        for (User user : users) {
            System.out.println(user);
        }
    }

    public static <T> List<T> selectAll(String sql, Class<T> clazz, Connection connection) throws SQLException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, NoSuchFieldException {
        PreparedStatement preparedStatement = connection.prepareStatement(sql);
        ResultSet resultSet = preparedStatement.executeQuery();
        ResultSetMetaData metaData = resultSet.getMetaData();
        int columnCount = metaData.getColumnCount();
        List<String> fieldNames = Arrays.asList(Arrays.stream(clazz.getDeclaredFields()).map(Field::getName).toArray(String[]::new));
        List<T> result = new ArrayList<>();
        while (resultSet.next()) {
            T obj = clazz.getConstructor().newInstance();
            for (int i = 1; i <= columnCount; i++) {
                String columnName = metaData.getColumnName(i);
                if (fieldNames.contains(columnName)) {
                    Field field = clazz.getDeclaredField(columnName);
                    field.setAccessible(true);
                    field.set(obj, resultSet.getObject(i));
                }
            }
            result.add(obj);
        }
        return result;
    }

    public static Connection getConnection(String url, String user, String password) throws SQLException {
        return DriverManager.getConnection(url, user, password);
    }
}
